use axum::{
    body::Bytes,
    extract::{FromRequest, Request},
    response::{IntoResponse, Response},
};
use serde::de::DeserializeOwned;
use validator::Validate;

pub mod chat;
pub mod message;
pub mod user;

pub struct ValidatedJson<T>(pub T);

// 自定义验证错误
#[derive(Debug)]
pub struct ValidationError(pub validator::ValidationErrors);

// 错误响应处理
impl IntoResponse for ValidationError {
    fn into_response(self) -> Response {
        let errors = self.0;
        let response = axum::Json(serde_json::json!({
            "error": "Validation failed",
            "details": errors
        }));
        (http::StatusCode::UNPROCESSABLE_ENTITY, response).into_response()
    }
}

impl<S, T> FromRequest<S> for ValidatedJson<T>
where
    T: DeserializeOwned + Validate + 'static,
    S: Send + Sync,
{
    type Rejection = Response;

    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
        let bytes = Bytes::from_request(req, state).await.map_err(|e| {
            (
                axum::http::StatusCode::BAD_REQUEST,
                format!("Failed to read body: {e:?}",),
            )
                .into_response()
        })?;

        // 解析JSON
        let value = match serde_json::from_slice::<T>(&bytes) {
            Ok(value) => value,
            Err(e) => {
                return Err((
                    axum::http::StatusCode::BAD_REQUEST,
                    format!("Invalid JSON: {e}"),
                )
                    .into_response())
            }
        };

        // 执行验证
        if let Err(e) = value.validate() {
            return Err(ValidationError(e).into_response());
        }

        Ok(ValidatedJson(value))
    }
}

pub fn validate_is_not_empty(str: &str) -> Result<(), validator::ValidationError> {
    if str.is_empty() {
        // the value of the username will automatically be added later
        return Err(validator::ValidationError::new("is not empty"));
    }

    Ok(())
}
